package cn.ronghuanet.auth.service.impl;

import cn.ronghuanet.auth.annotation.RonghuanetPermission;
import cn.ronghuanet.auth.domain.Permission;
import cn.ronghuanet.auth.mapper.PermissionMapper;
import cn.ronghuanet.auth.service.IPermissionScanService;
import cn.ronghuanet.auth.service.IPermissionService;
import cn.ronghuanet.base.enums.RequestTypeEnum;
import cn.ronghuanet.base.util.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class PermissionScanServiceImpl implements IPermissionScanService {

    @Autowired
    private  IPermissionService permissionService;

    @Value("${permission.base-package}")
    private  String url;

    @Transactional
    @Override
    public void scan() {
        permissionService.delete();
        ArrayList<Permission> list = new ArrayList<>();
        // 1. 获取所有执行路径下的类 Controller   list
        //
        List<Class> clazzs = ClassUtils.getAllClassName(url);
        // 2. 循环controller
        for (Class clazz: clazzs) {
            //      2.1 判断是否有@RonghuanetPermission
            RonghuanetPermission annotation = (RonghuanetPermission)clazz.getAnnotation(RonghuanetPermission.class);
            // 这里是获取RequestMapping.class 注解的信息
            RequestMapping annotation2 = (RequestMapping)clazz.getAnnotation(RequestMapping.class);
            String classUrl = annotation2.value()[0];
            if(Objects.isNull(annotation)){
                continue;
            }
            Permission parent = new Permission();
            parent.setUrl(classUrl);
            parent.setDescs(annotation.desc());
            parent.setName(annotation.name());
            parent.setSn(clazz.getSimpleName());
            permissionService.insert(parent);
            //      2.2 如果有权限注解  获取类里面所有的方法
            Method[] methods = clazz.getMethods();
            // 3.遍历所以的方法 判断是否有@RonghuanetPermission
            for (Method method: methods) {
                RonghuanetPermission annotation1 = method.getAnnotation(RonghuanetPermission.class);
                //  3.1 没有不处理
                if(Objects.isNull(annotation1)){
                    continue;
                }
                //  3.2 获取注解上的信息 name  desc 封装对象
                Permission permission = new Permission();
                permission.setName(annotation1.name());
                permission.setDescs(annotation1.desc());
                // sn 是权限的唯一标识 controllerName:methodName
                //  clazz.getSimpleName() 字节码对象.getSimpleName 获取Controller的名字
                permission.setSn(clazz.getSimpleName()+":"+method.getName());
                // 获取url Controller的requestMapping 中的值 + method的requestMapping中的值
                // 选中一段代码  ctrl + alt + m
                String methodUrl = getMethodUrl(method);
                permission.setUrl(classUrl+methodUrl);
                permission.setParent(parent);
                permissionService.insert(permission);
                list.add(permission);
            }

        }

        // 4. 入库
    }

    private String getMethodUrl(Method method){
        String methodUrl = "";
        // 取枚举中定义的所有的请求类型
        RequestTypeEnum[] requestTypeEnums = RequestTypeEnum.values();
        for (RequestTypeEnum typeEnum : requestTypeEnums) {
            // 根据枚举中的不同的请求类型的class获取该类型对应的注解对象
            Annotation annotation = method.getAnnotation(typeEnum.getRequestType());
            // 如果该请求类型注解不存在就跳过
            if(Objects.isNull(annotation)){
                continue;
            }
            try {
                // 如果该请求类型注解存在,就获取它里面的value方法
                Class<? extends Annotation> aClass = annotation.annotationType();
                Method annotationMethod = aClass.getMethod("value");
                // 通过invoke调用该对象的value方法,获取结果
                // 反射执行 方法 方法名.invoke(对象)
                String[] value = (String[]) annotationMethod.invoke(annotation);
                // 如果value不为空且长度大于0,就赋值给methodUrl,并跳出循环
                if(value != null && value.length > 0){
                    methodUrl = value[0];
                    break;
                }
            }catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        return methodUrl;

    }

   /* private String getMethodUrl(Method method) {
        String methodUrl = "";
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if(Objects.nonNull(getMapping)){
            methodUrl = getMapping.value().length>0?getMapping.value()[0]:"";
        }

        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if(Objects.nonNull(postMapping)){
            methodUrl = postMapping.value().length>0?postMapping.value()[0]:"";
        }

        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if(Objects.nonNull(putMapping)){
            methodUrl = putMapping.value().length>0?putMapping.value()[0]:"";
        }

        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if(Objects.nonNull(patchMapping)){
            methodUrl = patchMapping.value().length>0?patchMapping.value()[0]:"";
        }

        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if(Objects.nonNull(deleteMapping)){
            methodUrl = deleteMapping.value().length>0?deleteMapping.value()[0]:"";
        }
        return methodUrl;
    }*/





}
